import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.security.MessageDigest;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class FileDealer {
    public static void main(String[] args) {
        log.info("请输入想要保留的目录(仓库)：");
        Scanner scanner = new Scanner(System.in);
        String warePath = scanner.next();

        log.info("请输入想要清理的目录(临时目录)：");
        Scanner scanner2 = new Scanner(System.in);
        String tempPath = scanner2.next();

        //log.info("请输入需要替换替换掉的字符：");
        //Scanner scanner3 = new Scanner(System.in);
        //String replacedStr = scanner3.next();

        File[] filesInWare = getFiles(warePath);
        File[] filesTemp = getFiles(tempPath);
        final Integer[] num = {0};
        if (filesInWare != null && filesTemp != null) {

            // 仅对比和重命名(不删除)
            onlyCompareAndRenameWithForBreak(filesInWare, filesTemp, num);

            // 对比后删除重复的临时文件，并重命名仓库文件
            //compareAndDeleteTempAndRenameWareFile(filesInWare, filesTemp, num);

        } else {
            log.info("输入目录至少有一个不存在！");
        }

		/*File file = new File("C:\\Software\\D-backup\\Aisteel\\Images\\向日葵\\sunflower01.jpg");
		File file = new File("C:\\Software\\D-backup\\Aisteel\\Images\\向日葵\\向日葵002");
		long length = file.length();
		long time = file.lastModified();
		String ctime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(time));
		System.out.println("length:" + length);
		System.out.println("ctime:" + ctime);
		File file1 = new File("C:\\Software\\D-backup\\Aisteel\\Images\\向日葵\\sunflower01002.jpg");
		long length1 = file1.length();
		long time1 = file1.lastModified();
		String ctime1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(time1));
		System.out.println("length1:" + length1);
		System.out.println("ctime1:" + ctime1);
		if (length == length1 && time == time1) {
			System.out.println("删除：" + file1);
			//file1.deleteOnExit();
			file1.delete();
			log.info("{} 删除完毕！", file1);
		}*/
    }

    /**
     * 获取指定路径中的文件
     *
     * @param path 路径
     * @return 文件集合
     */
    private static File[] getFiles(String path) {
        File file = new File(path);
        return file.listFiles();
    }

    /**
     * 测试重命名
     */
    @Test
    public void testRenameFile() {
        // 对比后删除重复的临时文件，并重命名仓库文件
        //onlyRename(getFiles("E:\\From-iPhone\\test001_apple"), "00");
//        onlyRename(getFiles("E:\\From-iPhone\\100APPLE"), "20220930cSaved_");
//        onlyRename(getFiles("E:\\From-iPhone\\图片"), "20220930_MD5_toBeDel_");
//        onlyRename(getFiles("E:\\From-iPhone\\test001_apple"), "20220930_MD5_toBeSaved_");
//        onlyRename(getFiles("E:\\From-iPhone\\test002_baidudist"), "20220930_MD5_toBeDel_");
//        onlyRename(getFiles("E:\\From-iPhone\\100APPLE"), "20221003_MD5_toBeSaved_");
//        onlyRename(getFiles("E:\\From-iPhone\\图片"), "20221003_MD5_toBeDel_");
        onlyRename(getFiles("E:\\From-iPhone\\100APPLE"), "0000_toBeSaved_MD5_");
//        onlyRename(getFiles("E:\\From-iPhone\\图片"), "0000_toBeDeleted_MD5_");
        onlyRename(getFiles("E:\\From-iPhone\\视频"), "0000_toBeDeleted_MD5_");
    }

    /**
     * 测试对比并重命名
     */
    @Test
    public void testCompareAndRename() {
//        File[] filesInWare = getFiles("E:\\From-iPhone\\test001_apple");
//        File[] filesTemp = getFiles("E:\\From-iPhone\\test002_baidudist");
        File[] filesInWare = getFiles("E:\\From-iPhone\\100APPLE");
//        File[] filesTemp = getFiles("E:\\From-iPhone\\图片");
        File[] filesTemp = getFiles("E:\\From-iPhone\\视频");
        final Integer[] num = {0};
        if (filesInWare != null && filesTemp != null) {

            // 仅对比和重命名(不删除)
            onlyCompareAndRenameWithForBreak(filesInWare, filesTemp, num);

            // 对比后删除重复的临时文件，并重命名仓库文件
            //compareAndDeleteTempAndRenameWareFile(filesInWare, filesTemp, num);

        } else {
            log.info("输入目录至少有一个不存在！");
        }
    }

    /**
     * 测试对比并删除
     */
    @Test
    public void testCompareAndDelete() {
//        File[] filesInWare = getFiles("E:\\From-iPhone\\test001_apple");
//        File[] filesTemp = getFiles("E:\\From-iPhone\\test002_baidudist");
//        File[] filesInWare = getFiles("E:\\From-iPhone\\100APPLE");
        File[] filesInWare = getFiles("E:\\From-iPhone\\103APPLE");
//        File[] filesTemp = getFiles("E:\\From-iPhone\\图片");
        File[] filesTemp = getFiles("E:\\From-iPhone\\视频");
        final Integer[] num = {0};
        if (filesInWare != null && filesTemp != null) {

            // 仅对比和重命名(不删除)
            compareAndDelete(filesInWare, filesTemp, num);

        } else {
            log.info("输入目录至少有一个不存在！");
        }
    }

    /**
     * 仅对比和重命名(不删除)
     *
     * @param filesInWare 目标仓库中的文件
     * @param filesTemp   临时文件
     * @param num         序列号
     */
    private static void onlyCompareAndRename(File[] filesInWare, File[] filesTemp, Integer[] num) {
        Arrays.stream(filesInWare).forEach(oneFileInWare -> {
            if (oneFileInWare.isFile()) {
                Arrays.stream(filesTemp).forEach(oneTempFile -> {
                    if (oneTempFile.isFile()) {
                        // (临时目录)中的文件
                        String fileMD5OfOneTempFile = getFileMD5(oneTempFile);
                        // (仓库)中的文件
                        String fileMD5OfOneFileInWare = getFileMD5(oneFileInWare);
                        if (fileMD5OfOneTempFile.equals(fileMD5OfOneFileInWare)) {
                            //oneTempFile.delete();
                            //log.info("删除临时文件 {} 成功！", oneTempFile);
//                            oneTempFile.renameTo(new File(oneTempFile.getParent() + "\\" + String.format("%04d", num[0]) + "_toBeDeletedMD5_" + oneTempFile.getName()));
//                            oneTempFile.renameTo(new File(oneTempFile.getParent() + "\\" + String.format("%04d", num[0]) + "_MD5_" + oneTempFile.getName()));
                            oneTempFile.renameTo(new File(oneTempFile.getParent() + "\\" + "20220930_MD5_toBeDel_" + oneTempFile.getName()));
                            log.info("☆☆临时文件 {} 的MD5值为： {} ，并已被重命名，标记为待删除！", String.format("%15s", oneTempFile.getName()), fileMD5OfOneTempFile);

//                            oneFileInWare.renameTo(new File(oneFileInWare.getParent() + "\\" + String.format("%04d", num[0]) + "_toBeSavedMD5_" + oneFileInWare.getName()));
//                            oneFileInWare.renameTo(new File(oneFileInWare.getParent() + "\\" + String.format("%04d", num[0]) + "_MD5_" + oneFileInWare.getName()));
                            oneFileInWare.renameTo(new File(oneFileInWare.getParent() + "\\" + "20220930_MD5_toBeSaved_" + oneFileInWare.getName()));
                            log.info("★★原始文件“{}”的MD5值为：“{}”，并已被重命名，标记为待保存！\n", String.format("%15s", oneFileInWare.getName()), fileMD5OfOneTempFile);
                            num[0]++;
                        } else {
                            // Other operation002
                            Path path = oneTempFile.toPath();
                            //log.info("toPath: {}", path);
                        }
                    }
                });
            }
        });
    }

    /**
     * 仅对比和重命名(不删除)-使用For-break
     *
     * @param filesInWare 目标仓库中的文件
     * @param filesTemp   临时文件
     * @param num         序列号
     */
    private static void onlyCompareAndRenameWithForBreak(File[] filesInWare, File[] filesTemp, Integer[] num) {
        List<File> fileTempList = Arrays.stream(filesTemp).collect(Collectors.toList());
//        Iterator<File> fileTempList = (Iterator<File>) fileTempList;
        for (File oneFileInWare : filesInWare) {
            try {
                BasicFileAttributes wareFileAttributes = Files.readAttributes(oneFileInWare.toPath(), BasicFileAttributes.class);
                long wareFileSize = wareFileAttributes.size();
                FileTime wareFileTime = wareFileAttributes.lastModifiedTime();

//                while (fileTempList.hasNext()) {
//                    File oneTempFile = fileTempList.next();
                for (File oneTempFile : fileTempList) {
                    if (oneTempFile.isFile()) {
                        BasicFileAttributes tempFileAttributes = Files.readAttributes(oneTempFile.toPath(), BasicFileAttributes.class);
                        long tempFileSize = tempFileAttributes.size();
                        FileTime tempFileTime = tempFileAttributes.lastModifiedTime();
                        if (wareFileSize == tempFileSize && wareFileTime.equals(tempFileTime)) {

                            String name = oneFileInWare.getName();
                            boolean matched = false;
                            if (oneFileInWare.isFile() && !name.substring(name.indexOf('.')).equalsIgnoreCase(".MOV")) {
                                // 本次内容为文件，并且格式非.MOV
//                                while (fileTempList.hasNext()) {
//                                    File oneTempFile = fileTempList.next();
                                // (临时目录)中的文件
                                String fileMD5OfOneTempFile = getFileMD5(oneTempFile);
                                // (仓库)中的文件
                                String fileMD5OfOneFileInWare = getFileMD5(oneFileInWare);
                                if (fileMD5OfOneTempFile.equals(fileMD5OfOneFileInWare)) {
                                    //oneTempFile.delete();
                                    //log.info("删除临时文件 {} 成功！", oneTempFile);
//                                    oneTempFile.renameTo(new File(oneTempFile.getParent() + "\\" + "20221003_MD5_toBeDel_" + oneTempFile.getName()));
                                    oneTempFile.renameTo(new File(oneTempFile.getParent() + "\\" + String.format("%04d", num[0]) + "_toBeDeleted_MD5_" + oneTempFile.getName()));
                                    log.info("☆☆临时文件 {} 的MD5值为： {} ，并已被重命名，标记为待删除！", String.format("%15s", oneTempFile.getName()), fileMD5OfOneTempFile);

//                                    oneFileInWare.renameTo(new File(oneFileInWare.getParent() + "\\" + "20221003_MD5_toBeSaved_" + name));
                                    oneFileInWare.renameTo(new File(oneFileInWare.getParent() + "\\" + String.format("%04d", num[0]) + "_toBeSaved_MD5_" + oneFileInWare.getName()));
                                    log.info("★★原始文件“{}”的MD5值为：“{}”，并已被重命名，标记为待保存！\n", String.format("%15s", name), fileMD5OfOneTempFile);
                                    num[0]++;
                                    matched = true;
                                    fileTempList.remove(oneTempFile);
                                    break;
                                }
                            } else if (oneFileInWare.isFile()) {
                                //oneTempFile.delete();
                                //log.info("删除临时文件 {} 成功！", oneTempFile);
                                // 视频文件，只比较大小和最后修改时间
                                oneTempFile.renameTo(new File(oneTempFile.getParent() + "\\" + String.format("%04d", num[0]) + "_toBeDeleted_MD5_" + oneTempFile.getName()));
                                log.info("☆☆临时文件 {} 的大小为： {}，最后修改时间为：{} ，并已被重命名，标记为待删除！", String.format("%15s", oneTempFile.getName()), tempFileSize, tempFileTime);

                                oneFileInWare.renameTo(new File(oneFileInWare.getParent() + "\\" + String.format("%04d", num[0]) + "_toBeSaved_MD5_" + name));
                                log.info("★★原始文件“{}”的大小为：“{}，最后修改时间为：{}”，并已被重命名，标记为待保存！\n", String.format("%15s", name), wareFileSize, wareFileTime);
                                num[0]++;
                                fileTempList.remove(oneTempFile);
                                break;
                            }
                        }
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            /*if (matched) {
                fileTempList.remove();
            }*/
        }
    }

    /**
     * 对比并删除指定文件夹中重复的文件
     *
     * @param filesInWare 目标仓库中的文件
     * @param filesTemp   临时文件
     * @param num         序列号
     */
    private static void compareAndDelete(File[] filesInWare, File[] filesTemp, Integer[] num) {
        List<File> fileTempList = Arrays.stream(filesTemp).collect(Collectors.toList());
        for (File oneFileInWare : filesInWare) {
            try {
                BasicFileAttributes wareFileAttributes = Files.readAttributes(oneFileInWare.toPath(), BasicFileAttributes.class);
                long wareFileSize = wareFileAttributes.size();
                FileTime wareFileTime = wareFileAttributes.lastModifiedTime();
                for (File oneTempFile : fileTempList) {
                    if (oneTempFile.isFile()) {
                        BasicFileAttributes tempFileAttributes = Files.readAttributes(oneTempFile.toPath(), BasicFileAttributes.class);
                        long tempFileSize = tempFileAttributes.size();
                        FileTime tempFileTime = tempFileAttributes.lastModifiedTime();
                        if (wareFileSize == tempFileSize && wareFileTime.equals(tempFileTime)) {

                            String name = oneFileInWare.getName();
                            boolean matched = false;
                            if (oneFileInWare.isFile() && !name.substring(name.indexOf('.')).equalsIgnoreCase(".MOV")) {
                                // 本次内容为文件，并且格式非.MOV
                                // (临时目录)中的文件
                                String fileMD5OfOneTempFile = getFileMD5(oneTempFile);
                                // (仓库)中的文件
                                String fileMD5OfOneFileInWare = getFileMD5(oneFileInWare);
                                if (fileMD5OfOneTempFile.equals(fileMD5OfOneFileInWare)) {
                                    oneTempFile.delete();
                                    log.info("删除临时文件 {} 成功！", oneTempFile);

                                    oneFileInWare.renameTo(new File(oneFileInWare.getParent() + "\\" + String.format("%04d", num[0]) + "_saved_MD5_" + oneFileInWare.getName()));
                                    log.info("★★原始文件“{}”的MD5值为：“{}”，并已被重命名，标记为已保存！\n", String.format("%15s", name), fileMD5OfOneTempFile);
                                    num[0]++;
                                    matched = true;
                                    fileTempList.remove(oneTempFile);
                                    break;
                                }
                            } else if (oneFileInWare.isFile()) {
                                // 视频文件，大小和最后修改时间相同，即可删除重复文件
                                oneTempFile.delete();
                                log.info("删除重复的临时文件 {} 成功！", oneTempFile);

                                oneFileInWare.renameTo(new File(oneFileInWare.getParent() + "\\" + "20220930_toBeSaved_" + name));
                                log.info("★★原始文件“{}”的大小为：“{}，最后修改时间为：{}”，并已被重命名，标记为保已存！\n", String.format("%15s", name), wareFileSize, wareFileTime);
                                num[0]++;
                                fileTempList.remove(oneTempFile);
                                break;
                            }
                        }
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            /*if (matched) {
                fileTempList.remove();
            }*/
        }
    }

    /**
     * 仅重命名
     *
     * @param filesInWare 目标仓库中的文件
     */
    private static void onlyRename(File[] filesInWare, String replacedStr) {
        Arrays.stream(filesInWare).forEach(oneFileInWare -> {
//            if (oneFileInWare.isFile() && oneFileInWare.getName().contains(replacedStr)) {
            if (oneFileInWare.isFile()
                    && oneFileInWare.getName().length() > replacedStr.length()
                    && oneFileInWare.getName().contains("d_MD5_")) {

//                oneFileInWare.renameTo(new File(oneFileInWare.getParent() + "\\" + oneFileInWare.getName().replaceAll(replacedStr, "")));
                oneFileInWare.renameTo(new File(oneFileInWare.getParent() + "\\" + oneFileInWare.getName().substring(replacedStr.length())));
                log.info("★★原始文件“{}”已被重命名为“{}”！\n", String.format("%15s", oneFileInWare.getName()), oneFileInWare.getName().replaceAll(replacedStr, ""));
            } else if (oneFileInWare.isDirectory()) {
                String path = oneFileInWare.getPath();
                File[] files = getFiles(path);
                // 递归调用本方法
                onlyRename(files, replacedStr);
            }
        });
    }

    /**
     * 对比后删除重复的临时文件，并重命名仓库文件
     *
     * @param filesInWare 目标仓库中的文件
     * @param filesTemp   临时文件
     * @param num         序列号
     */
    private static void compareAndDeleteTempAndRenameWareFile(File[] filesInWare, File[] filesTemp, Integer[] num) {
        Arrays.stream(filesInWare).forEach(oneFileInWare -> {
            if (oneFileInWare.isFile()) {
                Arrays.stream(filesTemp).forEach(oneTempFile -> {
                    if (oneTempFile.isFile()) {
                        // (临时目录)中的文件
                        String fileMD5OfOneTempFile = getFileMD5(oneTempFile);
                        // (仓库)中的文件
                        String fileMD5OfOneFileInWare = getFileMD5(oneFileInWare);
                        if (fileMD5OfOneTempFile.equals(fileMD5OfOneFileInWare)) {
                            oneTempFile.delete();
                            log.info("删除临时文件 {} 成功！", oneTempFile);

//                            oneFileInWare.renameTo(new File(oneFileInWare.getParent() + "\\" + String.format("%04d", num[0]) + "_toBeSavedMD5_" + oneFileInWare.getName()));
//                            oneFileInWare.renameTo(new File(oneFileInWare.getParent() + "\\" + String.format("%04d", num[0]) + "_MD5_" + oneFileInWare.getName()));
                            oneFileInWare.renameTo(new File(oneFileInWare.getParent() + "\\" + "20220930_MD5_" + oneFileInWare.getName()));
                            log.info("★★原始文件“{}”的MD5值为：“{}”，并已被重命名，标记为待保存！\n", String.format("%15s", oneFileInWare.getName()), fileMD5OfOneTempFile);
                            num[0]++;
                        }
                    }
                });
            }
        });
    }

    /**
     * 获取指定图片的MD5码
     *
     * @param file 指定图片
     * @return 指定图片的MD5码
     */
    public static String getFileMD5(File file) {
        if (!file.isFile()) {
            return null;
        }
        // 创建MessageDigest对象，添加MD5处理
        // <p>The {@code digest} method can be called once for a given number
        //of updates. After {@code digest} has been called, the MessageDigest
        //object is reset to its initialized state.
        MessageDigest digest = null;
        FileInputStream fileInputStream = null;
        //byte buffer[] = new byte[1024];
        byte buffer[] = new byte[Math.toIntExact(file.length())];
        int len;
        try {
            digest = MessageDigest.getInstance("MD5");
            // 读取图片
            fileInputStream = new FileInputStream(file);

            /*while ((len = fileInputStream.read(buffer, 0, 1024)) != -1) {
                digest.update(buffer, 0, len);
            }*/

            // 解决“java.lang.IndexOutOfBoundsException”
            while ((len = fileInputStream.read(buffer, 0, buffer.length)) != -1) {
                digest.update(buffer, 0, len);
            }
            fileInputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        BigInteger bigInt = new BigInteger(1, digest.digest());
        // System.out.println(bigInt);
        // 返回16进制表示形式
        return bigInt.toString(16);
    }

    /*public static void main(String[] args) {
        File file1 = new File("134567876fhjkh.jpg");

        // String s = file1.getPath();
        File file2 = new File("2.jpg");

        String fileMD5 = getFileMD5(file1);

        String fileMD52 = getFileMD5(file2);

        System.out.println(file1.getName() + " 的MD5值是：" + fileMD5);
        System.out.println(file2.getName() + " 的MD5值是：" + fileMD52);

        if (fileMD5.equals(fileMD52)) {
            System.out.println("两张图片一致..");
        } else {
            System.out.println("两张图片不一致...");

        }
    }*/
}